package com.qianfeng.netty.http;

//
//                            _ooOoo_  
//                           o8888888o  
//                           88" . "88  
//                           (| -_- |)  
//                            O\ = /O  
//                        ____/`---'\____  
//                      .   ' \\| |// `.  
//                       / \\||| : |||// \  
//                     / _||||| -:- |||||- \  
//                       | | \\\ - /// | |  
//                     | \_| ''\---/'' | |  
//                      \ .-\__ `-` ___/-. /  
//                   ___`. .' /--.--\ `. . __  
//                ."" '< `.___\_<|>_/___.' >'"".  
//               | | : `- \`.;`\ _ /`;.`/ - ` : | |  
//                 \ \ `-. \_ __\ /__ _/ .-` / /  
//         ======`-.____`-.___\_____/___.-`____.-'======  
//                            `=---='  
//  
//         .............................................  
//                  佛祖镇楼                  BUG辟易  
//          佛曰:  
//                  写字楼里写字间，写字间里程序员；  
//                  程序人员写程序，又拿程序换酒钱。  
//                  酒醒只在网上坐，酒醉还来网下眠；  
//                  酒醉酒醒日复日，网上网下年复年。  
//                  但愿老死电脑间，不愿鞠躬老板前；  
//                  奔驰宝马贵者趣，公交自行程序员。  
//                  别人笑我忒疯癫，我笑自己命太贱；  
//  


import com.qianfeng.netty.http.anno.RequestMapping;
import com.qianfeng.netty.http.anno.RestController;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * Created by Jackiechan on 2022/7/6 11:27
 * 解析注解的
 *
 * @author Jackiechan
 * @version 1.0
 * @since 1.0
 */
public class RequestUtil {
    //请求地址和方法之间的关系
    public static Map<String, Method> url2Method = new HashMap<>();
    //当前地址是用哪个类来执行的
    public static Map<String, Object> url2Object = new HashMap<>();

    /**
     * 解析注解,处理地址和方法之间的关系
     */
    public static void inject() {
        //反射需要class,我们需要扫描所有的class
        CompletableFuture.runAsync(() -> {
            //找到所有的类,spring中是给我们了一个包名,然后去找里面所有的类
            String pacName = RequestUtil.class.getPackage().getName();
            //怎么找到这个包下面所有的类,其实就只找到这个目录下面所有的文件和文件夹中的文件
            //递归获取
            // System.err.println(pacName);
            //System.err.println(pacName.replace(".", "/"));
            //将包名转成了一个相对目录的路径
            String dir = pacName.replace(".", "/");

            //我们还得需要一个绝对路径,因为找文件需要绝对路径
            URL basePathUrl = RequestUtil.class.getClassLoader().getResource(".");
            System.err.println(basePathUrl);
            if (basePathUrl.getProtocol().startsWith("file")) {
                //System.err.println(basePathUrl.getPath());
                // 获取到绝对路径
                String basePath = basePathUrl.getPath();
                //以当前类所在的目录创建一个File对象
                File file = new File(basePath + dir);
                //递归
                getFiles(file, pacName);
                //看看映射关系
                System.err.println(url2Method);
            }

        });
    }


    public static void getFiles(File file, String pacName) {
        //获取到所有的文件
        File[] files = file.listFiles();
        for (File file1 : files) {
            if (file1.isDirectory()) {
                getFiles(file1, pacName + "." + file1.getName());
            } else {
                try {
                    // System.err.println(file1.getName());
                    // 拼接类的全限定名称
                    String className = pacName + "." + file1.getName().replace(".class", "");
                    System.err.println(className);
                    //反射加载这些类
                    Class<?> aClass = Class.forName(className);
                    //我们约定过,只有带有restcontroller的类才会去进行下一步,所以我们要从类上面获取注解
                    RestController restController = aClass.getAnnotation(RestController.class);
                    //有的类没有这个注解,所以restController是空的
                    if (restController != null) {
                        //创建我们的controller对象
                        Object controller = aClass.newInstance();
                        //类上面有这个注解
                        //获取请求地址
                        String basePath = "";
                        RequestMapping requestMapping = aClass.getAnnotation(RequestMapping.class);
                        if (requestMapping != null) {
                            //将类里面注解的值设置为基础的前缀路径
                            basePath = requestMapping.value();
                        }
                        //获取方法上面的这个注解
                        //获取到所有的方法
                        Method[] methods = aClass.getMethods();
                        for (Method method : methods) {
                            //获取到方法上的注解
                            RequestMapping mapping = method.getAnnotation(RequestMapping.class);
                            if (mapping != null) {
                                //获取到了方法上面的地址
                                String methodPath = mapping.value();
                                //真正的请求地址是上面的地址加上这个
                                String realRequestPath = basePath + methodPath;
                                //保存了地址和方法之期的关系
                                url2Method.put(realRequestPath, method);
                                //保存方法所在的类对象
                                url2Object.put(realRequestPath, controller);
                            }
                        }
                    }
                } catch (ClassNotFoundException e) {
                    throw new RuntimeException(e);
                } catch (InstantiationException e) {
                    throw new RuntimeException(e);
                } catch (IllegalAccessException e) {
                    throw new RuntimeException(e);
                }
            }

        }

    }
}
